package com.s2.m.btchat;

import java.io.IOException;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.List;
import javax.microedition.lcdui.TextBox;
import javax.microedition.lcdui.TextField;
import javax.microedition.midlet.*;
import javax.microedition.rms.RecordStoreException;

/**
 * @author Samik
 */
public class BTChat extends MIDlet implements CommandListener {

    /**
     * An reference to this instance of the this class
     */
    private static BTChat instance;
    /**
     * Title of this application
     */
    private final String appTitle = "S2 Chat";
    /**
     * Main menu list
     */
    private List menu;
    /**
     * Menu Item strings
     */
    private String[] menuItems = {"Active Chats", "Look for Friends", "Edit My Profile",
        "Device Status", "Settings", "About"};
    /**
     * Menu Icons to go with texts
     */
    private Image[] menuIcons = new Image[6];
    /**
     * index of the selected menu item
     */
    private int menuIndex;
    /**
     * Display of the current midlet
     */
    private Display display;

    /* Commands */
    private Command exitCommand = new Command("Exit", Command.EXIT, 0);
    private Command startServiceCmd = new Command("Start Service",
            Command.SCREEN, 2);
    private Command stopServiceCmd = new Command("Stop Service",
            Command.SCREEN, 2);
    private Command changeUsernameCmd = new Command("Change Username",
            Command.SCREEN, 3);
    private Command okCommand = new Command("OK", Command.SCREEN, 0);
    private Command cancelCommand = new Command("Cancel", Command.CANCEL, 1);
    /**
     * Preferences object profile stores the profile prefs
     */
    private Preferences profile;
    /**
     * A Preferences object to store the application preferences
     */
    private Preferences conf;

    /* Declaration of Other Objects*/
    private DeviceDiscovery deviceDiscovery = new DeviceDiscovery(this);
    /**
     * TextBox to enter the username
     */
    private TextBox usernameBox;
    /**
     * Reference to the Chat Server
     */
    private Server chatServer;

    /* Constractor */
    public BTChat() {
        //Get the display for this midlet
        display = Display.getDisplay(this);

        //create the menu icons
        initializeMenuIcons();

        //Create the menu
        menu = new List(appTitle, List.IMPLICIT, menuItems, menuIcons);

        // Add commands to the menu (list)
        menu.addCommand(exitCommand);
        menu.addCommand(changeUsernameCmd);

        // listen for events
        menu.setCommandListener(this);

        //Initialise username textbox
        usernameBox = new TextBox("Enter User Name", "", 8,
                TextField.ANY);
        usernameBox.addCommand(okCommand);
        usernameBox.addCommand(cancelCommand);
        usernameBox.setCommandListener(this);

        //Show the user interface
        showUI();

        loadProfilePref();
        loadAppConfiguration();

        // Now start the chat service on this device
        if (Settings.isChatServiceAtStartUp()) {
            startChatService();
        } else {
            menu.addCommand(startServiceCmd);
        }
        instance = this;
    }

    private void startChatService() {
        //Create a Thread with an instance of Server
        chatServer = new Server();
        Thread t = new Thread(chatServer, "Server");
        t.start();
    }

    public void chatServiceStarted(boolean status) {
        if (status = false) {
            Alert alert = new Alert("Chat Service could not be started. Make sure phone's bluetooth is turned On");
            Displayable prevDisplayble = display.getCurrent();
            display.setCurrent(alert, prevDisplayble);
        } else {
            menu.addCommand(stopServiceCmd);

        }
    }

    /**
     * Creates Image objects appropriate for the current screen resolution
     * from the icons available in Resource. This images are used in the menu
     * along with the string part
     */
    private void initializeMenuIcons() {
        int h = display.getBestImageHeight(Display.LIST_ELEMENT);
        String dim = (h >= 16) ? "16x16" : "12x12";
        try {
            menuIcons[0] = null;
            menuIcons[1] = Image.createImage("/com/s2/m/res/img/find" + dim + ".png");
            menuIcons[2] = Image.createImage("/com/s2/m/res/img/user" + dim + ".png");
            menuIcons[3] = Image.createImage("/com/s2/m/res/img/mobile_phone" + dim + ".png");
            menuIcons[4] = Image.createImage("/com/s2/m/res/img/settings" + dim + ".png");
            menuIcons[5] = Image.createImage("/com/s2/m/res/img/application" + dim + ".png");
        } catch (IOException ex) {
            ex.printStackTrace();
        }

    }

    public Server getChatServer() {
        if (Server.isRunning()) {
            return chatServer;
        } else {
            return null;
        }
    }

    public void showUI() {
        display.setCurrent(menu);
    }

    public void startApp() {
    }

    public void pauseApp() {
    }

    public void destroyApp(boolean unconditional) {
        //save profile settings
        saveProfilePref();
        saveAppConfiguration();
    }

    public void commandAction(Command c, Displayable d) {
        if (c == exitCommand && d == menu) {
            destroyApp(true);
            notifyDestroyed();
        } else if (c == List.SELECT_COMMAND && d == menu) {
            menuIndex = menu.getSelectedIndex();
            switch (menuIndex) {
                case 0:
                    new ActiveChats();
                    break;
                case 1:
                    deviceDiscovery.showUI();
                    break;
                case 2:
                    (new MyProfile(this)).show();
                    break;
                case 3:
                    (new DeviceStatus(this)).show();
                    break;
                case 4:
                    (new Settings(this)).showUI();
                    break;
                case 5:
                    new About(this);
                default:
                    break;
            }
        } else if (c == stopServiceCmd && d == menu) {
            if (Server.isRunning()) {//if ChatServer is running
                chatServer.destroy();
                menu.removeCommand(stopServiceCmd);
                menu.addCommand(startServiceCmd);
            }
        } else if (c == startServiceCmd) {
            startChatService();
        } else if (c == changeUsernameCmd) {
            usernameBox.setString(MyProfile.getUsername());
            display.setCurrent(usernameBox);
        } else if (c == okCommand && d == usernameBox) {
            //update profile with new username
            MyProfile.setUsername(usernameBox.getString());
            MyProfile.setModified(true);//profile is modified
            showUI();//back to main screen
        } else if (c == cancelCommand && d == usernameBox) {
            showUI();//back to main screen
        }
    }

    /**
     * Shows an alert to the user with the exception message. When the
     * user dismissed the alert the main menu is displayed
     * @param e Exception to be displayed
     */
    public void showException(Exception e) {
        Alert a = new Alert("Exception", e.toString(), null, null);
        a.setTimeout(Alert.FOREVER);
        display.setCurrent(a, menu);
    }

    /**
     * Loads profile preferences from persistent storage and set the
     * corresponding values in <code>MyProfile<code>
     */
    private void loadProfilePref() {
        try {
            profile = new Preferences("profile");
        } catch (RecordStoreException ex) {
            ex.printStackTrace();
        }

        MyProfile.setUsername(profile.get("username"));
        MyProfile.setFullName(profile.get("fullname"));
        MyProfile.setAboutMe(profile.get("aboutme"));
        MyProfile.setAge(profile.get("age"));
        MyProfile.setSex(profile.get("sex"));
        MyProfile.setProfession(profile.get("profession"));
    }

    /**
     * Saves profile preferences to persistent storage
     */
    private void saveProfilePref() {
        if (MyProfile.isModified()) {
            profile.put("username", MyProfile.getUsername());
            profile.put("fullname", MyProfile.getFullName());
            profile.put("aboutme", MyProfile.getAboutMe());
            profile.put("age", MyProfile.getAge());
            profile.put("sex", MyProfile.getSex());
            profile.put("profession", MyProfile.getProfession());
            try {
                profile.save();
            } catch (RecordStoreException ex) {
                ex.printStackTrace();
            }
        }
    }

    /**
     * Loads application settings from persistent storage
     */
    private void loadAppConfiguration() {
        try {
            conf = new Preferences("conf");
        } catch (RecordStoreException ex) {
            ex.printStackTrace();
        }
        String str1 = conf.get(Settings.SERVICE_AT_STARTUP);
        if (str1.equals("true")) {
            Settings.setChatServiceAtStartUp(true);
        } else if (str1.equals("false")) {
            Settings.setChatServiceAtStartUp(false);
        }

        String str2 = conf.get(Settings.ENABLE_SOUNDS);
        if (str2.equals("true")) {
            Settings.setSoundsEnabled(true);
        } else if (str2.equals("false")) {
            Settings.setSoundsEnabled(false);
        }
    }

    /**
     * Saves the application settings to persistent storage
     */
    private void saveAppConfiguration() {
        if (Settings.isModified()) {
            conf.put(Settings.SERVICE_AT_STARTUP,
                    Settings.isChatServiceAtStartUp() ? "true" : "false");
            conf.put(Settings.ENABLE_SOUNDS,
                    Settings.isSoundsEnabled() ? "true" : "false");

            try {
                conf.save();
            } catch (RecordStoreException ex) {
                ex.printStackTrace();
            }
        }
    }

    /**
     * Static method to get the last created instance of this class
     * @return Last created instance of the BTChat class, <code>null</code> if
     * no instance is available
     */
    public static BTChat getInstance() {
        return instance;
    }
    /**
     * Constant SYSTEM has the value 2
     */
    public static final int SYSTEM = 2;
    /**
     * Constant REMOTE_USER has the value 1
     */
    public static final int REMOTE_USER = 1;
    /**
     * Constant LOCAL_USER has the value 0
     */
    public static final int LOCAL_USER = 0;
}
